﻿using IronPython.Runtime;
using IronPython.Runtime.Types;
using Microsoft.Scripting.Actions;
using NFox.Pyeditor.Runtime;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace NFox.Pyeditor.Types
{
    public abstract class Valuetype : TypeBase, ITreeListItemModel
    {

        protected Valuetype(string text, object value)
        {
            Text = text;
            Value = value;
        }

        public dynamic Value { get; protected set; }

        public virtual bool IsCallable { get { return false; } }

        protected virtual void NewOverloads() { }

        public List<string> _overloads;
        public List<string> Overloads
        {
            get
            {
                if (_overloads == null)
                    NewOverloads();
                return _overloads;
            }
        }

        public virtual dynamic ClrType
        {
            get { return Application.GetValue("clr").GetClrType(Application.GetValue("type")(Value)); }
        }

        private const string NewStyleTypeName =
            "IronPython.NewTypes.System.Object_1$1";

        public static Valuetype GetValue(string text, object value, dynamic type = null)
        {

            if (type == null)
            {
                if (value == null)
                    return new None(text);
                type = Application.GetValue("type")(value);
            }

            //.Net数据类型
            if (value is NamespaceTracker)
                return new Namespace(text, value);
            if (value is ReflectedEvent.BoundEvent)
                return new Event(text, value);

            //Python数据类型
            if (value is PythonModule)
                return new Module(text, value);
            if (value is OldClass)
                return new Class(text, value);

            if (value is Method ||
                value is PythonFunction ||
                value is BuiltinFunction ||
                value is BuiltinMethodDescriptor ||
                value is ClassMethodDescriptor)
                return new Function(text, value);

            //类型
            if (value is PythonType)
            {
                type = Application.GetValue("clr").GetClrType(value);
                if (type.IsEnum)
                    return new Enum(text, value);
                else if (type.FullName == NewStyleTypeName)
                    return new Type(text, value);
                else
                    return new NetType(text, value);
            }

            if (type is ReflectedProperty)
                type = type.PropertyType;
            if (type is ReflectedPropertyTracker)
                type = type.DeclaringType;

            if (type is PythonType || type is System.Type)
            {

                dynamic t = Application.GetValue("clr").GetClrType(type);
                //Python对象
                if (value is OldInstance || t.FullName == NewStyleTypeName)
                {
                    //设置__call__按函数处理
                    if (Application.GetValue("callable")(value))
                        return new Function(text, value);
                    else
                        return new Variant(text, value);
                }
                return new NetVariant(text, value, type);
            }

            return new NetVariant(text, value);

        }

        public virtual Valuetype GetItem(string key)
        {
            if (Marshal.IsComObject(Value))
                return null;
            try { return Valuetype.GetValue(key, Application.GetValue("getattr")(Value, key)); }
            catch { return null; }
        }

        public virtual IEnumerable<Valuetype> GetItems()
        {
            List lst = Application.GetValue("clr").Dir(Value);
            if (lst != null)
            {
                foreach (string key in lst)
                {
                    dynamic obj = null;
                    try { obj = Application.GetValue("getattr")(Value, key); }
                    catch { }
                    yield return Valuetype.GetValue(key, obj);
                }
            }
        }

        public virtual string TypeName { get { return Application.GetValue("type")(Value).__name__; } }

        public string Data { get { return $"{Value}"; } }


        public virtual IEnumerable<ITreeListItemModel> GetChildren()
        {
            foreach (var value in GetItems())
            {
                yield return value;
            }
        }

        public virtual bool HasChildren
        {
            get { return true; }
        }

    }

    public class Variant : Valuetype
    {
        public Variant(string text, object value) : base(text, value) { }

        public override int ImageIndex { get { return 1; } }
        public override string ToolTipTitle { get { return $"变量:{Text}"; } }
        public override string ToolTipText { get { return $"类型:{ClrType.FullName}"; } }
    }

    public class None : Variant
    {

        public override Valuetype GetItem(string key)
        {
            return null;
        }

        public None(string text) : base(text, null) { }

        public override string ToolTipText { get { return $"None"; } }

        public override bool HasChildren
        {
            get { return false; }
        }

    }


    public class Function : Valuetype
    {

        public Function(string text, object value) : base(text, value) { }

        public override bool IsCallable { get { return true; } }

        protected override void NewOverloads()
        {
            var newfunc = Value;
            _overloads = new List<string>();
            if (Application.GetValue("hasattr")(newfunc, "Overloads"))
            {
                foreach (var func in newfunc.Overloads.Functions)
                    _overloads.Add(func.__doc__);
            }
            else if (newfunc.__doc__ != null)
            {
                var ms = Regex.Matches(newfunc.__doc__, $"{Text}\\(.*?\\)(->.*?)*");
                foreach (Match m in ms)
                    _overloads.Add(m.Value);
            }
        }

        public override int ImageIndex { get { return 3; } }
        public override string ToolTipTitle
        {
            get
            {
                string s = "";
                if (Overloads.Count > 1)
                    s = $"(+{Overloads.Count - 1}重载)";
                return $"函数:{Text}{s}";
            }
        }

        public override string ToolTipText
        {
            get
            {
                if (Overloads.Count > 0)
                    return Overloads[0].ToString();
                else
                    return Value.__doc__;
            }
        }
    }

    public class Module : Valuetype
    {
        public Module(string text, object value) : base(text, value) { }

        public override int ImageIndex { get { return 4; } }
        public override string ToolTipTitle { get { return $"模块:{Value.__name__}"; } }
        public override string ToolTipText { get { return Value.__doc__ ?? Value.__file__; } }
    }

    public class Class : Valuetype
    {
        public Class(string text, object value) : base(text, value) { }

        public override int ImageIndex { get { return 5; } }
        public override string ToolTipTitle { get { return $"经典类:{Value.__name__}"; } }
        public override string ToolTipText { get { return Value.__file__; } }
    }

    public class Type : Valuetype
    {
        public Type(string text, object value) : base(text, value) { }

        public override bool IsCallable { get { return Application.GetValue("callable")(Value.__new__); } }

        protected override void NewOverloads()
        {
            var newfunc = Value.__new__;
            _overloads = new List<string>();
            if (Application.GetValue("hasattr")(newfunc, "Overloads"))
            {
                foreach (var func in newfunc.Overloads.Functions)
                    _overloads.Add(func.__doc__);
            }
            else
            {
                _overloads.Add(newfunc.__doc__);
            }
        }

        public override int ImageIndex { get { return 5; } }
        public override string ToolTipTitle { get { return $"新式类:{Text}"; } }
        public override string ToolTipText
        {
            get
            {
                if (Application.GetValue("hasattr")(Value, "__doc__") && Value.__doc__ != null)
                    return Value.__doc__;
                else if(Value.__new__.__doc__ != null)
                    return Value.__new__.__doc__;
                return "";
            }
        }
    }


}
